/*
 *  Copyright (C) 2010 Glauco
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 * 
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.balisunrise.swing.transaction;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JPanel;
import org.balisunrise.annotation.IsEntityValid;
import org.balisunrise.annotation.PanelType;
import org.balisunrise.builder.BuilderException;
import org.balisunrise.common.BindingGroup;
import org.balisunrise.common.VisualEntityType;
import org.balisunrise.common.abstracts.AbstractLayoutable;
import org.balisunrise.swing.builder.FieldLayoutBuilder;

/**
 *
 * @author Glauco
 */
public class EntityPanel extends AbstractLayoutable
        implements org.balisunrise.common.EntityPanel<JPanel>, Serializable{

    private JPanel visualRepresentation;
    private FieldLayoutBuilder fieldLayoutBuilder;
    private Serializable entity;
    private PanelType type;
    private List<org.balisunrise.common.EntityPanel<JPanel>> associatedPanels;
    private BindingGroup bindingGroup;

    private static final String PROP_ENTITY = "entity";
    private static final String PROP_BINDINGGROUP = "bindingGroup";
    private static final String PROP_VISUAL_REPRESENTATION = "visualRepresentation";
    private static final String PROP_TYPE = "type";

    public EntityPanel(FieldLayoutBuilder fieldLayoutBuilder) {
        associatedPanels =
                new ArrayList<org.balisunrise.common.EntityPanel<JPanel>>();
        this.fieldLayoutBuilder = fieldLayoutBuilder;
    }

    public BindingGroup getBindingGroup() {
        return bindingGroup;
    }

    public void setBindingGroup(BindingGroup bindingGroup) {
        if (this.bindingGroup != null)
            this.unBind();

        if(!associatedPanels.isEmpty()){
            for (org.balisunrise.common.EntityPanel<JPanel> ap : associatedPanels) {
                ap.setBindingGroup(bindingGroup);
            }
        }else{
            createBindings(bindingGroup, this, PROP_ENTITY);
        }

        BindingGroup oldBindingGroup = this.bindingGroup;
        this.bindingGroup = bindingGroup;
        changeSupport.firePropertyChange(PROP_BINDINGGROUP,
                oldBindingGroup, bindingGroup);
    }

    public void setAssociatedPanels(
            List<org.balisunrise.common.EntityPanel<JPanel>>
            associatedPanels) {
        this.associatedPanels = associatedPanels;
    }

    public void setType(PanelType type) {
        PanelType oldType = this.type;
        this.type = type;
        changeSupport.firePropertyChange(PROP_TYPE, oldType, type);
    }

    public void setVisualRepresentation(JPanel visualRepresentation) {
        JPanel old = this.visualRepresentation;
        this.visualRepresentation = visualRepresentation;
        changeSupport.firePropertyChange(PROP_VISUAL_REPRESENTATION,
                old, visualRepresentation);
    }

    public JPanel getVisualRepresentation() {
        return visualRepresentation;
    }

    public Serializable getEntity() {
        return entity;
    }

    public void setEntity(Serializable entity) {
        Serializable oldEntity = getEntity();
        this.entity = entity;
        changeSupport.firePropertyChange(PROP_ENTITY, oldEntity,entity);
    }

    public PanelType getType() {
        return type;
    }

    public List<org.balisunrise.common.EntityPanel<JPanel>>
            getAssociatedPanels() {

        return associatedPanels;
    }

    public boolean isEntityValid() {
        // TODO: Ler @IsEntityValid do ActionMap
        for (Method method : getEntity().getClass().getMethods()) {
            if (method.isAnnotationPresent(IsEntityValid.class) &&
                    method.getParameterTypes().length == 0 &&
                    method.getReturnType().equals(Boolean.class)){
                try {
                    return (Boolean) method.invoke(getEntity());
                } catch (Exception ex) {
                    System.out.println(ex.getMessage() + "\n" + ex.getCause());
                }
            }
        }
        return true;
    }

    /**
     * Realiza o Vínculo entre os componentes visuais e os atributos da entidade.
     */
    public void bind() {
        if (bindingGroup != null)
            bindingGroup.bind();
        for (org.balisunrise.common.EntityPanel<JPanel> ap : associatedPanels) {
            ap.bind();
        }
    }

    /**
     * Desfaz o Vínculo entre os componentes visuais e os atributos da entidade.
     */
    public void unBind() {
        if (bindingGroup != null)
            bindingGroup.unbind();
        for (org.balisunrise.common.EntityPanel<JPanel> ap : associatedPanels) {
            ap.unBind();
        }
    }

    /**
     * Retorna o tipo do VisualEntity.<BR>
     * Sempre retornará ENTITY_PANEL.
     * @return VisualEntityType.ENTITY_PANEL
     */
    public VisualEntityType getVisualEntityType() {
        return VisualEntityType.ENTITY_PANEL;
    }

    public void buildLayout() {
        try{
            fieldLayoutBuilder.create(visualRepresentation, layouts);
        }catch(BuilderException bex){
            System.out.println("Falha ao construir Layout: " + bex.getMessage());
        }
    }
}
